package com.syspeak.modules.spring.web.servlet.view.xml;

import java.util.Map;

import javax.servlet.ServletException;

import org.springframework.oxm.Marshaller;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.web.servlet.view.xml.MarshallingView;

public class FilterMarshallingView extends MarshallingView {

	protected String modelKey;
	private Marshaller marshaller;

	@Override
	public void setModelKey(String modelKey) {
		this.modelKey = modelKey;
	}

	/**
	 * Sets the {@link Marshaller} to be used by this view.
	 */
	@Override
	public void setMarshaller(Marshaller marshaller) {
		Assert.notNull(marshaller, "'marshaller' must not be null");
		super.setMarshaller(marshaller);
		this.marshaller = marshaller;
	}

	/**
	 * Locates the object to be marshalled. The default implementation first attempts to look under the configured
	 * {@linkplain #setModelKey(String) model key}, if any, before attempting to locate an object of {@linkplain
	 * Marshaller#supports(Class) supported type}.
	 *
	 * @param model the model Map
	 * @return the Object to be marshalled (or <code>null</code> if none found)
	 * @throws ServletException if the model object specified by the {@linkplain #setModelKey(String) model key} is not
	 *                          supported by the marshaller
	 * @see #setModelKey(String)
	 */
	@Override
	protected Object locateToBeMarshalled(Map<String, Object> model) throws ServletException {
		if (this.modelKey != null) {
			Object o = model.get(this.modelKey);
			if (o == null) {
				throw new ServletException("Model contains no object with key [" + modelKey + "]");
			}
			if (!this.marshaller.supports(o.getClass())) {
				throw new ServletException("Model object [" + o + "] retrieved via key [" + modelKey
						+ "] is not supported by the Marshaller");
			}
			return o;
		}
		for (Object o : model.values()) {
			if (o != null && !(o instanceof BindingResult) && this.marshaller.supports(o.getClass())) {
				return o;
			}
		}
		return null;
	}
}
